﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.DirectoryServices;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Data;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml;

using AddProductLib;
using MessageBox = System.Windows.MessageBox;
using SkladLib;

namespace AddUserLib
{
    public partial class AddUserWin
    {

        #region Proměnné + metody
        
        private int _errors;
        private static int _celkovaCena;
        private int _pocetSetu;
        private readonly Hashtable _tabulkaVyskytu = new Hashtable();

        private readonly Zakaznik _zakaznik = new Zakaznik();

        private NovyZbozi _novyZbozi;

        private bool _upravit; // jestli uzivatel klikne na tlacitko Upravit
        private bool _zacitUlozit;
        private bool _canClose;

        private string _carovyKod = "";

        readonly List<String> _listPrefixu = new List<string>();

        private void Validation_Error(object sender, ValidationErrorEventArgs e)
        {
            if (e.Action == ValidationErrorEventAction.Added)
                _errors++;
            else
                _errors--;
        }

        private void UpdateCelkovaCena()
        {
            CheckKompletniSety();
            _celkovaCena = 0;

            foreach (NovyZbozi novyZbozi in list_SeznamZbozi.Items)
            {
                try
                {
                    _celkovaCena += int.Parse(novyZbozi.Cena);
                }
                catch (Exception ex)
                {
                    string sCena = novyZbozi.Cena;
                    if (sCena.Contains("za"))
                    {
                        sCena = sCena.Substring(0, sCena.IndexOf(" ", StringComparison.Ordinal));
                        _celkovaCena += int.Parse(sCena);
                    }
                    else
                        _celkovaCena += 0;
                }
            }

            tb_CelkovaCena.Text = _celkovaCena.ToString();
        }

        private void CheckKompletniSety()
        {
            foreach (string prefix1 in _listPrefixu)
            {
                switch (VratitPoradiPrefix(prefix1))
                {
                    case 1: // LY
                        foreach (string prefix2 in _listPrefixu)
                        {
                            switch (VratitPoradiPrefix(prefix2))
                            {
                                case 3: // BL
                                    foreach (string prefix3 in _listPrefixu.Where(prefix3 => VratitPoradiPrefix(prefix3) == 7))
                                    {
                                        int a = 0, b = 1, c = 2;
                                        // Set LY + BL + H
                                        foreach (NovyZbozi novyZbozi in list_SeznamZbozi.Items)
                                        {
                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    a = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                                case "BL":
                                                    b = int.Parse(novyZbozi.PocetDni); 
                                                    break;
                                                case "H":
                                                    c = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                            }
                                        }

                                        ArrayList pomPole = new ArrayList();
                                        for (int index = 0; index < list_SeznamZbozi.Items.Count; index++)
                                        {
                                            NovyZbozi novyZbozi = (NovyZbozi) list_SeznamZbozi.Items[index];
                                            if ((a != b) || (a != c)) continue;

                                            
                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    novyZbozi.Cena = ZjistitCenu(1, a) + " (za celý set)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "BL":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "H":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                            }
                                        }

                                        _tabulkaVyskytu[_pocetSetu + ""] = pomPole;
                                        _pocetSetu += 1;

                                        RefreshList();
                                    }
                                    break;
                                case 5: // BN
                                    foreach (string prefix3 in _listPrefixu.Where(prefix3 => VratitPoradiPrefix(prefix3) == 7))
                                    {
                                        int a = 0, b = 1, c = 2;
                                        // Set LY + BN + H
                                        foreach (NovyZbozi novyZbozi in list_SeznamZbozi.Items)
                                        {

                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    a = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                                case "BN":
                                                    b = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                                case "H":
                                                    c = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                            }
                                        }

                                        ArrayList pomPole = new ArrayList();
                                        for (int index = 0; index < list_SeznamZbozi.Items.Count; index++)
                                        {
                                            NovyZbozi novyZbozi = (NovyZbozi)list_SeznamZbozi.Items[index];
                                            if ((a != b) || (a != c)) continue;


                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    novyZbozi.Cena = ZjistitCenu(2, a) + " (za celý set)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "BN":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "H":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                            }
                                        }

                                        _tabulkaVyskytu[_pocetSetu + ""] = pomPole;
                                        _pocetSetu += 1;

                                        RefreshList();
                                    }
                                    break;
                                case 6: // B75
                                    foreach (string prefix3 in _listPrefixu.Where(prefix3 => VratitPoradiPrefix(prefix3) == 7))
                                    {
                                        int a = 0, b = 1, c = 2;
                                        // Set LY + BL + H
                                        foreach (NovyZbozi novyZbozi in list_SeznamZbozi.Items)
                                        {

                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    a = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                                case "B75":
                                                    b = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                                case "H":
                                                    c = int.Parse(novyZbozi.PocetDni);
                                                    break;
                                            }
                                        }

                                        ArrayList pomPole = new ArrayList();
                                        for (int index = 0; index < list_SeznamZbozi.Items.Count; index++)
                                        {
                                            NovyZbozi novyZbozi = (NovyZbozi)list_SeznamZbozi.Items[index];
                                            if ((a != b) || (a != c)) continue;


                                            switch (novyZbozi.Prefix)
                                            {
                                                case "LY":
                                                    novyZbozi.Cena = ZjistitCenu(3, a) + " (za celý set)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "B75":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                                case "H":
                                                    novyZbozi.Cena = "0 (zahrnutá v setu)";
                                                    pomPole.Add(index);
                                                    break;
                                            }
                                        }

                                        _tabulkaVyskytu[_pocetSetu + ""] = pomPole;
                                        _pocetSetu += 1;

                                        RefreshList();
                                    }
                                    break;
                            }  
                        }
                        break;

                    case 2: // SN
                        foreach (string prefix2 in _listPrefixu.Where(prefix2 => VratitPoradiPrefix(prefix2) == 4))
                        {
                            int a = 0, b = 1;
                            // Set LY + BL + H
                            foreach (NovyZbozi novyZbozi in list_SeznamZbozi.Items)
                            {
                                switch (novyZbozi.Prefix)
                                {
                                    case "SN":
                                        a = int.Parse(novyZbozi.PocetDni);
                                        break;
                                    case "BS":
                                        b = int.Parse(novyZbozi.PocetDni);
                                        break;
                                }
                            }

                            ArrayList pomPole = new ArrayList();
                            for (int index = 0; index < list_SeznamZbozi.Items.Count; index++)
                            {
                                NovyZbozi novyZbozi = (NovyZbozi)list_SeznamZbozi.Items[index];
                                if (a != b) continue;


                                switch (novyZbozi.Prefix)
                                {
                                    case "SN":
                                        novyZbozi.Cena = ZjistitCenu(4, a) + " (za celý set)";
                                        pomPole.Add(index);
                                        break;
                                    case "BS":
                                        novyZbozi.Cena = "0 (zahrnutá v setu)";
                                        pomPole.Add(index);
                                        break;
                                }
                            }

                            _tabulkaVyskytu[_pocetSetu + ""] = pomPole;
                            _pocetSetu += 1;

                            RefreshList();
                        }
                        break;
                }
            }
        }

        private void SmazatSet(int index)
        {
            ArrayList listProDeleni = null;

            for (int i = 0; i < _pocetSetu; i++)
            {
                foreach (ArrayList pomList in from DictionaryEntry entry in _tabulkaVyskytu
                                              where (string) entry.Key == (i + "")
                                              select (ArrayList) entry.Value
                                              into pomList where pomList.Cast<int>().Any(cislo => cislo == index)
                                              select pomList)
                {
                    listProDeleni = pomList;
                }
            }

            if (listProDeleni == null) return;
            int inkrement = 0;
            foreach (int a in from int cislo in listProDeleni select cislo - inkrement)
            {
                list_SeznamZbozi.Items.RemoveAt(a);
                _listPrefixu.RemoveAt(a);

                inkrement += 1;
            }
        }

        private static int VratitPoradiPrefix(string prefix)
        {
            switch (prefix)
            {
                case "LY":
                    return 1;
                    break;
                case "SN":
                    return 2;
                    break;
                case "BL":
                    return 3;
                    break;
                case "BS":
                    return 4;
                    break;
                case "BN":
                    return 5;
                    break;
                case "B75":
                    return 6;
                    break;
                case "H":
                    return 7;
                    break;
            }

            return 0;
        }

        private void RefreshList()
        {
            list_SeznamZbozi.Items.Refresh();
        }

        private int ZjistitCenu(int cisloSetu, int pocetDni)
        {
            int cena = 0;
            switch (cisloSetu)
            {
                case 1: // LY + BL + H
                case 4: // SN + BS
                    switch (pocetDni)
                    {
                        case 1:
                            cena = 120;
                            break;
                        case 2:
                            cena = 200;
                            break;
                        case 3:
                            cena = 260;
                            break;
                        case 4:
                            cena = 310;
                            break;
                        case 5:
                            cena = 350;
                            break;
                        case 6:
                            cena = 400;
                            break;
                        case 7:
                            cena = 450;
                            break;
                        default:
                            cena = 450 + (pocetDni - 7) * 50;
                            break;
                    }
                    break;

                case 2: // LY + BN + H
                    switch (pocetDni)
                    {
                        case 1:
                            cena = 80;
                            break;
                        case 2:
                            cena = 130;
                            break;
                        case 3:
                            cena = 180;
                            break;
                        case 4:
                            cena = 220;
                            break;
                        case 5:
                            cena = 250;
                            break;
                        case 6:
                            cena = 270;
                            break;
                        case 7:
                            cena = 290;
                            break;
                        default:
                            cena = 290 + (pocetDni - 7) * 20;
                            break;
                    }
                    break;

                case 3: // LY + B75 + H
                    switch (pocetDni)
                    {
                        case 1:
                            cena = 40;
                            break;
                        case 2:
                            cena = 70;
                            break;
                        case 3:
                            cena = 90;
                            break;
                        case 4:
                            cena = 100;
                            break;
                        case 5:
                            cena = 110;
                            break;
                        case 6:
                            cena = 120;
                            break;
                        case 7:
                            cena = 130;
                            break;
                        default:
                            cena = 130 + (pocetDni - 7) * 10;
                            break;
                    }
                    break;
            }

            return cena;
        }

        #endregion

        #region Check číslo JIS karty

        private void tb_cisloKarty_TextChanged(object sender, TextChangedEventArgs e)
        {
            if(tb_cisloKarty.Text.Length < 5) return;

            DirectoryEntry myLdapConnection = new DirectoryEntry()
            {
                Path = "LDAP://ldap.zcu.cz/ou=rfc2307,o=zcu,c=cz",
                AuthenticationType = AuthenticationTypes.None,
            };

            DirectorySearcher search = new DirectorySearcher(myLdapConnection)
                {
                    Filter = "(jisChipNo=" + tb_cisloKarty.Text + ")"
                };
            search.PropertiesToLoad.Add("sn;lang-cs");          // prijmeni
            search.PropertiesToLoad.Add("givenname;lang-cs");   // jmeno

            try
            {
                SearchResult result = search.FindOne();

                if (result == null) return;

                ResultPropertyCollection fields = result.Properties;

                if (fields.PropertyNames != null)
                    foreach (String ldapField in fields.PropertyNames)
                    {
                        switch (ldapField.ToString(CultureInfo.InvariantCulture))
                        {
                            case "givenname;lang-cs":
                                tb_Jmeno.Text = fields[ldapField][0].ToString();
                                break;
                            case "sn;lang-cs":
                                tb_Prijmeni.Text = fields[ldapField][0].ToString();
                                break;
                        }
                    }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Chyba připojení", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void bt_SmazatCisloKarty_Click(object sender, RoutedEventArgs e)
        {
            tb_cisloKarty.Text = "";
            tb_Jmeno.Text = "";
            tb_Prijmeni.Text = "";
        }

        #endregion

        #region Události Form

        public AddUserWin()
        {
            InitializeComponent();

            grid_1.DataContext = _zakaznik;
        }

        private void Window_Loaded_1(object sender, RoutedEventArgs e)
        {
            var procesy = Process.GetProcessesByName("grab-usb");
            if (procesy.Length == 0)
            {
                MessageBox.Show("Není spuštěn program grab-usb.exe", "Chyba");

                tb_cisloKarty.Visibility = Visibility.Hidden;
            }

            tb_cisloKarty.Focus();
            _CenaZmenena = false;
        }

        private void Window_Closing_1(object sender, CancelEventArgs e)
        {
            if (list_SeznamZbozi.Items.Count == 0) return;

            if(_canClose == false)
            e.Cancel = MessageBoxResult.Yes !=
                       MessageBox.Show("Opravdu chcete zrušit všechny změny", "Upozornění", MessageBoxButton.YesNo,
                                       MessageBoxImage.Warning);
        }

        private void Window_PreviewTextInput_1(object sender, TextCompositionEventArgs e)
        {
            switch (e.Text)
            {
                case "-":
                    InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("en-US"));
                    _zacitUlozit = true;
                    _carovyKod = "";
                    e.Handled = true;
                    break;
                case "(":
                    InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("cs-CZ"));
                    _zacitUlozit = false;
                    e.Handled = true;
                        
                    try
                    {
                        // Otevrit okno NovyProdukt
                        WPridatZbozi oknoPridatZbozi = new WPridatZbozi(_carovyKod);
                        oknoPridatZbozi.PridatZbozi += Form_PridatClicked;
                        oknoPridatZbozi.ShowDialog();
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("Produkt není zaznamenán v databázi", "Upozornění", MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                    break;

                default:
                    if (_zacitUlozit)
                    {
                        e.Handled = true;
                        _carovyKod += e.Text;
                    }
                    break;
            }
            
        }

        #endregion

        #region Seznam produktů - Přidat, Upravit, Smazat

        private void Form_PridatClicked(object sender, PridatZboziEventArgs e)
        {
            try
            {
                _novyZbozi = new NovyZbozi(e.CarovyKod, e.Prefix, e.NazevProduktu, e.Cena, e.OdDne, e.PocetDni, e.Rezerva, e.KeDni);
            }
            catch (Exception)
            {
                // nove zbozi, ktere nema carovy kod
                _novyZbozi = new NovyZbozi(string.Empty, e.Prefix, e.NazevProduktu, e.Cena, e.OdDne, e.PocetDni, e.Rezerva, e.KeDni);
            }

            if (_upravit) return;

            list_SeznamZbozi.Items.Add(_novyZbozi);
            _listPrefixu.Add(_novyZbozi.Prefix);
        }

        private void bt_PridatDoSeznamu_Click(object sender, RoutedEventArgs e)
        {
            WPridatZbozi oknoPridatZbozi = new WPridatZbozi();
            oknoPridatZbozi.PridatZbozi += Form_PridatClicked;
            oknoPridatZbozi.ShowDialog();

            UpdateCelkovaCena();
        }

        private void bt_Upravit_Click(object sender, RoutedEventArgs e)
        {
            int indexSelectedZbozi = list_SeznamZbozi.SelectedIndex;

            if (indexSelectedZbozi >= 0)
            {
                _upravit = true;
                WPridatZbozi oknoPridatZbozi = new WPridatZbozi(_novyZbozi);
                oknoPridatZbozi.PridatZbozi += Form_PridatClicked;
                oknoPridatZbozi.ShowDialog();

                list_SeznamZbozi.Items.RemoveAt(indexSelectedZbozi);
                list_SeznamZbozi.Items.Insert(indexSelectedZbozi, _novyZbozi);
            }

            else
                MessageBox.Show("Není vybrané žádné zboží !", "Upozornění", MessageBoxButton.OK, MessageBoxImage.Warning);

            _upravit = false;
            UpdateCelkovaCena();
        }

        private void bt_Smazat_Click(object sender, RoutedEventArgs e)
        {
            if (list_SeznamZbozi.Items.Count > 0)
            {
                int selectedIndex = list_SeznamZbozi.SelectedIndex;

                NovyZbozi vybrane = (NovyZbozi) list_SeznamZbozi.Items.GetItemAt(selectedIndex);

                if (vybrane.Cena.Contains("("))
                {
                    if (MessageBoxResult.Yes ==
                    MessageBox.Show(
                        "Tento předmět je součástí kompletního setu. Smazat tento předmět ze seznamu znamená smazat VŠECHNY předměty, které daný set obsahuje !!\nChcete pokračovat ?",
                        "Upozornění", MessageBoxButton.YesNo,
                        MessageBoxImage.Warning))

                        SmazatSet(selectedIndex);
                }

                else
                {
                    list_SeznamZbozi.Items.Remove(list_SeznamZbozi.SelectedItem);
                    _listPrefixu.RemoveAt(selectedIndex);

                    // select next row
                    if (selectedIndex <= list_SeznamZbozi.Items.Count - 1)
                    {
                        list_SeznamZbozi.SelectedIndex = selectedIndex;
                    }
                    else // select last row
                    {
                        list_SeznamZbozi.SelectedIndex = list_SeznamZbozi.Items.Count - 1;
                    }
                }

                UpdateCelkovaCena();
            }

            else
                MessageBox.Show("Není vybrané žádné zboží !", "Upozornění", MessageBoxButton.OK, MessageBoxImage.Warning);
        }
    
        private void list_SeznamZbozi_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                int indexSelectedZbozi = list_SeznamZbozi.SelectedIndex;
                NovyZbozi vybrane = (NovyZbozi)list_SeznamZbozi.Items.GetItemAt(indexSelectedZbozi);
            
                if (int.Parse(vybrane.Cena) != 0)
                    bt_Upravit.IsEnabled = true;
            }
            catch (Exception ex)
            {
                bt_Upravit.IsEnabled = false;
            }
        }

        #endregion

        #region Potvrdit, Storno

        public delegate void NovaZakazkaHandler(object sender, NovaZakazkaEventArgs e);

        public event NovaZakazkaHandler NovaZakazka;

        private void bt_OK_Click(object sender, RoutedEventArgs e)
        {
            if (_errors > 0)
                MessageBox.Show("Jméno nebo přijmení není platné !", "Upozornění", MessageBoxButton.OK,
                                MessageBoxImage.Stop);

            else if (list_SeznamZbozi.Items.Count == 0)
                MessageBox.Show("Nebylo vybrané žádné zboží !", "Upozornění", MessageBoxButton.OK,
                                MessageBoxImage.Stop);

            else
            {
                List<NovyZbozi> seznamZbozi = new List<NovyZbozi>();
                for (int i = 0; i < list_SeznamZbozi.Items.Count; i++)
                {
                    // Upraveno David Rosko
                    NovyZbozi novyZboziItem = (NovyZbozi)list_SeznamZbozi.Items.GetItemAt(i);
                    seznamZbozi.Add(novyZboziItem);

                    if (Zbozi.ExistZboziByCode(novyZboziItem.CarovyKod))            //Nastavit pujceno pouze pokud je v DB
                    {
                        Zbozi zboziZDatabaze = Zbozi.GetZboziByCode(novyZboziItem.CarovyKod); //Nactu zbozi z databaze
                        zboziZDatabaze.SetPujceno(true);   //Nastavim ze je pujceno
                    }
                    //******************************
                }

                NovaZakazkaEventArgs args = new NovaZakazkaEventArgs(tb_cisloKarty.Text,
                                                                        tb_Jmeno.Text,
                                                                        tb_Prijmeni.Text, tb_OP.Text, tb_tel.Text, 
                                                                        seznamZbozi, _celkovaCena);
                NovaZakazka(this, args);

                _canClose = true;
                this.Close();
            }
        }

        private void bt_Storno_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBoxResult.Yes == MessageBox.Show("Opravdu chcete stornovat všechny změny ?", "Upozornění", MessageBoxButton.YesNo,
                                MessageBoxImage.Warning))
                this.Close();
        }

        #endregion

        private void tb_CelkovaCena_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            e.Handled = !IsTextAllowed(e.Text);
        }

        private static bool IsTextAllowed(string text)
        {
            Regex regex = new Regex("[^0-9.-]+");
            return !regex.IsMatch(text);
        }

        private bool _CenaZmenena = true;
        private void tb_CelkovaCena_TextChanged(object sender, TextChangedEventArgs e)
        {
            String puvodniText = tb_CelkovaCena.Text;
            if (tb_CelkovaCena.Text.Length == 0)
            {
                UpdateCelkovaCena();
                _CenaZmenena = false;
            }

            else
            {
                if (_CenaZmenena == false)
                {
                    if (MessageBoxResult.Yes ==
                        MessageBox.Show("Opravdu chcete určit vlastní celkovou cenu ?", "Upozornění", MessageBoxButton.YesNo,
                                        MessageBoxImage.Warning))
                    {
                        _CenaZmenena = true;
                    }
                    else
                    {
                        bt_OK.Focus();
                    }
                }

            }
        }
    }
}
